import { getToken } from '@/utils/auth'
import errorCode from '@/utils/errorCode'
import { toast, showConfirm, tansParams } from '@/utils/common'
import useUserStore from '@/store/modules/user'

// 定义请求配置的接口
interface IRequestConfig {
  url: string
  method?: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH'
  data?: Record<string, any>
  header?: Record<string, string>
  params?: Record<string, any>
  timeout?: number
}

// 定义响应数据的类型
interface IResponseData {
  code?: number
  msg?: string
  [key: string]: any // 允许其他任意属性
}

// 扩展 errorCode 以允许字符串索引
type ErrorCodeType = typeof errorCode & { [key: string]: string }

// 确保 errorCode 拥有字符串索引签名
const extendedErrorCode: ErrorCodeType = errorCode as ErrorCodeType

// 全局请求封装
const base_url = 'http://localhost:8080'
const timeout = 10000

// 需要修改token，和根据实际修改请求头
const request = async (config: IRequestConfig): Promise<any> => {
  const userStore = useUserStore()

  // 构建 URL 和处理 GET 请求参数
  let url = config.url
  if (config.params) {
    url += '?' + tansParams(config.params)
    url = url.replace('?&', '?') // 如果有多个参数，去除多余的 & 符号
  }

  // 确保 method 是大写的，并且提供默认值 'GET'
  const method = (config.method?.toUpperCase() || 'GET') as
    | 'GET'
    | 'POST'
    | 'PUT'
    | 'DELETE'
    | 'OPTIONS'
    | 'HEAD'
    | 'TRACE'
    | 'CONNECT'
    | undefined

  const data = config.data || {}
  const headers: Record<string, string> = {
    Authorization: getToken() || '',
    'Content-Type': 'application/json;charset=UTF-8',
    ...config.header,
  }

  return new Promise((resolve, reject) => {
    // 显示加载提示
    uni.showLoading({
      title: '加载中...',
    })

    uni.request({
      url: base_url + url,
      method: method, // 使用定义好的 RequestMethod 类型
      header: headers,
      data: data,
      timeout: timeout,
      success(res) {
        let responseData: IResponseData
        if (typeof res.data === 'object' && res.data !== null) {
          responseData = res.data as IResponseData
        } else {
          responseData = { msg: String(res.data), code: res.statusCode || 200 }
        }

        const code = responseData.code || res.statusCode || 200
        const msg = responseData.msg || ''

        if (code === 200) {
          resolve(responseData)
        } else {
          switch (code) {
            case 401:
              showConfirm('登录状态已过期，您可以继续留在该页面，或者重新登录?').then(
                ({ confirm }) => {
                  if (confirm) {
                    userStore.logOut().then(() => {
                      uni.redirectTo({
                        url: '/pages/login/login',
                      })
                    })
                  }
                },
              )
              reject(new Error('无效的会话，或者会话已过期，请重新登录。'))
              uni.clearStorageSync()
              break
            case 404:
              reject(new Error(msg))
              break
            default:
              reject(new Error(msg))
              break
          }
        }
      },
      fail(err) {
        console.error(err)
        if (err.errMsg.includes('request:fail')) {
          uni.showToast({
            title: '网络异常',
            icon: 'error',
            duration: 2000,
          })
        } else {
          uni.showToast({
            title: '未知异常',
            duration: 2000,
          })
        }
        reject(err)
      },
      complete() {
        // 不管成功还是失败都会执行
        uni.hideLoading()
        uni.hideToast()
      },
    })
  }).catch((error) => {
    return Promise.reject(error)
  })
}

export default request
